package edu.tfh.s2.ehkbot.gerete;

import java.util.Vector;

import edu.tfh.s2.ehkbot.daten.GeraeteRegistration;
import edu.tfh.s2.ehkbot.daten.Protokoll;
import edu.tfh.s2.ehkbot.gerete.aktoren.MotorAktor;
import edu.tfh.s2.ehkbot.gerete.sensoren.Sensor;
import edu.tfh.s2.ehkbot.steuerung.BusAdresse;

/**
 * EHKBot ist eine Komposition aus den Bot Bestandteilen.
 * 
 * @author s2zehn
 */
public class EHKBot {
	/**
	 * Wird geworfen wenn beim Initilaiesieren der Komponenten ein Fehler passiert.
	 */
	public class EHKBotInitFail extends Exception {
		private static final long serialVersionUID = -6700147954093576674L;
		private BusAdresse busAdresse;

		/**
		 * Kontruktor für EHKBotInitFail
		 * @param message Die Nachricht.
		 * @param busadresse Die BusAdresse der komponente.
		 */
		public EHKBotInitFail(String message, BusAdresse busadresse) {
			super(message);
			this.busAdresse = busadresse;
		}
	}

	/**
	 * Bildet die Status Fahren und nicht Fahren auf FAHRBEREIT und FAHRBETRIEBEINGESTELT ab.
	 */
	public enum EHKBotStatus {
		FAHRBEREIT, FAHRBETRIEBEINGESTELT
	}

	private Fahrgestell fahrgestell;
	private Greifarm greifarm;
	private Hebebuehne hebebuehne;
	private EHKBotStatus status;

	/**
	 * Erzeugt die Komponenten und stellt Fahrbereichtschaft ein.
	 * 
	 * @throws EHKBotInitFail
	 *             Wenn eine Komponente nicht erzeugt werden konnte.
	 */
	public EHKBot() throws EHKBotInitFail {
		greifarm = new Greifarm();
		fahrgestell = new Fahrgestell();
		hebebuehne = new Hebebuehne();
		fahrbetriebAufnaehmen();
		testeSensoren();
	}

	/**
	 * Geht alle erzeugen Motroen im System durch und aktiviert sie.
	 * 
	 * @throws EHKBotInitFail
	 *             Wenn eine Komponente nicht erzeugt werden konnte.
	 */
	public void fahrbetriebAufnaehmen() throws EHKBotInitFail {
		status = EHKBotStatus.FAHRBEREIT;
		Protokoll.getInstanc().protokolliere("EHKBot", "fahrbetriebAufnaehmen", 1, Protokoll.TYP.INFO);
		Vector<MotorAktor> motorenListe = GeraeteRegistration.getInstance().getMotorAktorListe();
		for (int i = 0; i < motorenListe.size(); ++i) {
			MotorAktor motor = motorenListe.get(i);
			motor.aktiviere();
			if (!motor.istAktiviert()) {
				BusAdresse busAdr = motor.getBusAdresse();
				String msg = String.format(
					"Sensor mit der adresse %s meldete Fehler beim aktivieren",
					motor.getBusAdresse().toString());
				throw new EHKBotInitFail(msg, busAdr);
			}
		}
	}

	/**
	 * Getter Methode für Fahrgestell.
	 * 
	 * @return Das Fahrgestell.
	 */
	public Fahrgestell getFahrgestell() {
		return fahrgestell;
	}

	/**
	 * Getter Methode für Greifarm.
	 * 
	 * @return Den Greifarm.
	 */
	public Greifarm getGreifarm() {
		return greifarm;
	}

	/**
	 * Getter Methode für Hebebuehne.
	 * 
	 * @return Die Hebebuehne.
	 */
	public Hebebuehne getHebebuehne() {
		return hebebuehne;
	}

	/**
	 * Getter Methode für Hebebuehne.
	 * 
	 * @return Den Status des Bots.
	 */
	public EHKBotStatus getStatus() {
		return status;
	}

	/**
	 * Geht alle erzeugen Motoren im System durch und deaktiviert sie.
	 */
	public void stelleFahrbetriebEin() {
		status = EHKBotStatus.FAHRBETRIEBEINGESTELT;
		Protokoll.getInstanc().protokolliere("EHKBot", "stelleFahrbetriebEin", 1, Protokoll.TYP.INFO);
		Vector<MotorAktor> motorenListe = GeraeteRegistration.getInstance().getMotorAktorListe();
		for (int i = 0; i < motorenListe.size(); ++i) {
			motorenListe.get(i).deaktiviere();
		}
	}

	/**
	 * Geht alle erzeugen Sensoren im System durch und prüft sie mit hilfe der Sensor.testeFunktion() Methode.
	 * 
	 * @throws EHKBotInitFail
	 *             Wenn ein Sensor bei den Aufruf von Sensor.testeFunktion() angibt das er nicht Funktioniert.
	 */
	public void testeSensoren() throws EHKBotInitFail {
		Vector<Sensor> sensorListe = GeraeteRegistration.getInstance().getSensorListe();
		for (int i = 0; i < sensorListe.size(); ++i) {
			Sensor sensor = sensorListe.get(i);
			if (!sensor.testeFunktion()) {
				throw new EHKBotInitFail(String.format(
					"Sensor mit der adresse %s meldete Fehler beim aktivieren",
					sensor.getBusAdresse().toString()), sensor.getBusAdresse());
			}
		}
	}
}
